package com.th.coupon.service.impl;

import com.alibaba.fastjson.JSON;
import com.th.coupon.common.constant.Constant;
import com.th.coupon.constant.CouponStatus;
import com.th.coupon.dao.CouponDao;
import com.th.coupon.entity.Coupon;
import com.th.coupon.service.IRabbitMqService;
import com.th.coupon.vo.CouponRabbitMessage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 消息接收处理
 * @author 涂航
 */
@Slf4j
@Component
public class RabbitMqServiceImpl implements IRabbitMqService {

    private final CouponDao couponDao;

    @Autowired
    public RabbitMqServiceImpl(CouponDao couponDao) {
        this.couponDao = couponDao;
    }

    /**
     * {@link QueueBinding} 设置队列绑定 {@link Queue} 对列{@link Exchange}交换机
     * @param couponRabbitMessage {@link CouponRabbitMessage} 反序列化后的message对象
     */
    @Override
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = Constant.RabbitMq.DISCOUNT_USER_COUPON_QUEUE,durable = "true"),
            exchange = @Exchange(name = Constant.RabbitMq.DISCOUNT_USER_COUPON_EXCHANGE, durable = "true",type = ExchangeTypes.TOPIC),
            key={Constant.RabbitMq.DISCOUNT_USER_COUPON_KEY}
    ))
    public void consumeCouponRabbitMqMessage(@Payload CouponRabbitMessage couponRabbitMessage) {
        Optional<CouponRabbitMessage> rabbitMqMessage = Optional.ofNullable(couponRabbitMessage);
        if (rabbitMqMessage.isPresent()){
            //获取发送的rabbitMq的消息
            CouponRabbitMessage message = rabbitMqMessage.get();

            log.info("Receive CouponRabbitMessage : {}",message.toString());

            CouponStatus status = CouponStatus.of(message.getStatus());

            switch (status){
                case USABLE:
                    break;
                case USED:
                    processUsedCoupons(couponRabbitMessage,status);
                    break;
                case EXPIRED:
                    processExpiredCoupons(couponRabbitMessage,status);
                    break;
            }
        }
    }

    /**
     * 更新已使用优惠卷的DB操作
     * @param couponRabbitMessage {@link CouponRabbitMessage}
     * @param status 优惠卷状态
     */
    private void processUsedCoupons(CouponRabbitMessage couponRabbitMessage
            ,CouponStatus status){
        //TODO 给用户发送短信
        processCouponsByStatus(couponRabbitMessage,status);
    }

    /**
     * 更新过期优惠卷DB操作
     * @param couponRabbitMessage {@link CouponRabbitMessage}
     * @param status 优惠卷状态
     */
    private void processExpiredCoupons(CouponRabbitMessage couponRabbitMessage
            ,CouponStatus status){
        //TODO 给用户发送推送
        processCouponsByStatus(couponRabbitMessage,status);
    }
    /**
     * 修改对应的优惠卷状态，同步数据到DB
     * @param couponRabbitMessage {@link CouponRabbitMessage}
     * @param status 优惠卷状态
     */
    private void processCouponsByStatus(CouponRabbitMessage couponRabbitMessage
            ,CouponStatus status){
        List<Coupon> coupons = couponDao.findAllById(couponRabbitMessage.getIds());
        //查询的集合为空并且与消息传递的优惠卷id数量不一致
        if(CollectionUtils.isEmpty(coupons)
        || coupons.size() != couponRabbitMessage.getIds().size()){
            log.error("Can Not Find Right Coupon Info : {}", JSON.toJSONString(couponRabbitMessage));
            //TODO 发送邮件
            return;
        }

        //修改状态
        coupons.forEach(coupon -> coupon.setStatus(status));
        //更新数据库
        log.info("CouponRabbitMessage Op Coupon count : {}",couponDao.saveAll(coupons).size());
    }





}
